﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Windows.Forms;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using IMLibrary4.Protocol;
using IMLibrary4.AV;
using OurSoftware;
using IMLibrary4.Net;
using IMLibrary4.WebP;

namespace IMLibrary4.AV
{
    /// <summary>
    /// 远程桌面控制对像j
    /// </summary>
    public class RemoteDesktopControl : RtpP2PTransmit
    {
        #region 变量
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serverEP"></param>
        public RemoteDesktopControl(IPEndPoint serverEP)
            : base(serverEP)
        {

        }

        /// <summary>
        /// 标识是否初始化组件
        /// </summary>
        bool IsIni;

        PictureBox picbox = null;

        /// <summary>
        /// 图像宽度放大系数X
        /// </summary>
        public float uX = 1.60f;
        /// <summary>
        /// 图像高度放大系数X
        /// </summary>
        public float uY = 1.60f;

        /// <summary>
        /// 桌面显示控件
        /// </summary>
        public PictureBox picBox
        {
            set
            {
                picbox = value;
                #region 鼠标键盘事件
                if (picbox != null)
                { 
                    picbox.MouseMove+= (s, e) =>
                        {
                            UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
                            DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseMove;
                            DesketOrder.X = (int)(e.X * uX);
                            DesketOrder.Y = (int)(e.Y * uY );
                            sendRtcpControlPacket(DesketOrder);//发送命令
                        };
                   
                    picbox.MouseClick += (s, e) =>
                    {
                        UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
                        DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseClick;
                        DesketOrder.X = (int)(e.X * uX);
                        DesketOrder.Y = (int)(e.Y * uY);
                        sendRtcpControlPacket(DesketOrder);//发送命令
                    };
                    picbox.MouseDoubleClick += (s, e) =>
                    {
                        UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
                        DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseDoubleClick;
                        DesketOrder.X = (int)(e.X * uX);
                        DesketOrder.Y = (int)(e.Y * uY);
                        sendRtcpControlPacket(DesketOrder);//发送命令
                    };
                    picbox.MouseDown += (s, e) =>
                    {
                        UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
                        DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseLeftDown;
                        if (e.Button == MouseButtons.Right)
                            DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseRightDown;
                        DesketOrder.X = (int)(e.X * uX);
                        DesketOrder.Y = (int)(e.Y * uY);
                        sendRtcpControlPacket(DesketOrder);//发送命令
                    };
                    picbox.MouseUp += (s, e) =>
                    {
                        UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
                        DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseLeftUp;
                        if (e.Button == MouseButtons.Right)
                            DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.MouseRightUp;
                        DesketOrder.X = (int)(e.X * uX);
                        DesketOrder.Y = (int)(e.Y * uY);
                        sendRtcpControlPacket(DesketOrder);//发送命令
                    };
                }
                #endregion
            }
            get { return picbox; }
        }
        /// <summary>
        /// 是否控制端(控制端不用发送桌面图像给对方)
        /// </summary>
        public bool IsControler = false;
        /// <summary>
        /// 桌面截图源
        /// </summary>
        OurSoftware.Video.ScreenCaptureStream sc = null;
        /// <summary>
        /// 标记是否收到过图片侦
        /// </summary>
        bool IsReceiveFirstImage = false;
     
        #endregion
         
        #region 事件
        public delegate void ReceiveFirstImageEventHandler(object sender,Image image);
        /// <summary>
        /// 收到第一侦图片事件
        /// </summary>
        public event ReceiveFirstImageEventHandler ReceiveFirstImage;
        #endregion

        #region 发送键盘键值
        /// <summary>
        /// 发送键盘键值
        /// </summary>
        /// <param name="key"></param>
        public void sendKeyUp(Keys key)
        {
            UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
            DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.KeyUp;
            DesketOrder.KeyCode = (byte)key;
            sendRtcpControlPacket(DesketOrder);//发送命令
        }
        /// <summary>
        /// 发送键盘键值
        /// </summary>
        /// <param name="key"></param>
        public void sendKeyDown(Keys key)
        {
            UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
            DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.KeyDown;
            DesketOrder.KeyCode = (byte)key;
            sendRtcpControlPacket(DesketOrder);//发送命令
        }
        #endregion

        #region 发送远程控制命令
        private void sendRtcpControlPacket(UdpRemoteDesketOrder DesketOrder)
        {
            sendFrame(DesketOrder.ToBytes());

            //Rtcp.RtcpPacket rtcpPack = new Rtcp.RtcpPacket(Rtcp.RtcpPacket.RtcpPacketType.ApplicationSpecific);
            ////rtcpPack.Payload = DesketOrder.ToBytes();
            //rtcpPack.Channel = 1;
            //rtcpPack.BlockCount=12;
            //Rtcp.ApplicationSpecific app = new Rtcp.ApplicationSpecific((uint)DateTime.UtcNow.Ticks,1);
            //app.Payload = DesketOrder.ToBytes();

            //ApplicationSpecific - qtsi
            //byte[] example = new byte[] { 0x81, 0xcc, 0x00, 0x06, 0x4e, 0xc8, 0x79, 0x50, 0x71, 0x74, 0x73, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x61, 0x74, 0x00, 0x04, 0x00, 0x00, 0x00, 0x14 };
            //Rtcp.RtcpPacket asPacket = new Rtcp.RtcpPacket(example, 0);
            //app = new Rtcp.ApplicationSpecific(asPacket);
            //if (app.Name != "qtsi") throw new Exception("Invalid App Packet Type");
            //Test making a packet with a known length in bytes

            //Rtcp.SourceDescription sd = new Rtcp.SourceDescription();
            //sd.Add(new Rtcp.SourceDescription.SourceDescriptionChunk(0x1AB7C080, new Rtcp.SourceDescription.SourceDescriptionItem(Rtcp.SourceDescription.SourceDescriptionType.CName, "FLABIA-PC"))); // SSRC(4) ItemType(1), Length(1), ItemValue(9), End(1) =  16 Bytes                        
            //asPacket = sd; // Header = 4 Bytes
            //if (asPacket.Length != 16 || asPacket.ToBytes()[3] != 4) throw new Exception("Invalid Length");

            //app.Channel = 1;
            //sendRtcpPack(app);
        }
        #endregion

        #region 收到命令，处理命令
        /// <summary>
        /// 收到命令，处理命令
        /// </summary>
        /// <param name="DesketOrder"></param>
        private void ExcuteOrder(UdpRemoteDesketOrder DesketOrder)
        {
        

        }
        #endregion

        #region 初始化控件/通信组件
        /// <summary>
        /// 初始化控件/通信组件
        /// </summary>
        public void iniControls()
        {
            if (!IsIni)
                IsIni = true;//标识已经初始化
            else
                return; //如果已经初始化，则退出 
             
            Start();

            #region 收到RTP 侦事件
            RecFrameData += (sender, data) =>
            {
                if (!IsControler && data.Length == 12)
                {
                    UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder(data);
                    ExcuteOrder(DesketOrder);
                    return;
                }

                if (!IsReceiveFirstImage && ReceiveFirstImage != null && IsControler)
                {
                    IsReceiveFirstImage = true;
                    ReceiveFirstImage(this, null);
                }


                if (IsControler && picBox != null)
                {
                    #region MJPEG算法
                    //Rtp.JpegFrame j=new Rtp.JpegFrame(f);
                    //Image image = j.ToImage();
                    #endregion

                    #region webP算法
                    if (!System.IO.File.Exists("WebP.dll"))
                        WebPFormat.DeCompress();

                    Image image = WebPFormat.Load(data);
                    #endregion

                    delegateDrawDesktop d = new delegateDrawDesktop(DrawDesktop);
                    picBox.Invoke(d, image);
                     
                    UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
                    DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.NONE;
                    sendRtcpControlPacket(DesketOrder);//发送一个假操作，维持RTP Session
                    Console.WriteLine("发送假操作成功.");
                }

            };
            #endregion

            #region 收到RTP JPEG侦事件
            //RtpFrameChanged += (sender, f) =>
            //    {
            //        byte[] imageBuf = f.Assemble();

            //        if (!IsControler && imageBuf.Length == 12)
            //        {
            //            UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder(f.Assemble());
            //            ExcuteOrder(DesketOrder);
            //            return;
            //        }

            //        if (ReceiveFirstImage != null && !IsReceiveFirstImage)
            //        {
            //            IsReceiveFirstImage = true;
            //            ReceiveFirstImage(this, null);
            //        }


            //        if (picBox != null)
            //        {
            //            #region MJPEG算法
            //            //Rtp.JpegFrame j=new Rtp.JpegFrame(f);
            //            //Image image = j.ToImage();
            //            #endregion

            //            #region webP算法
            //            Image image = WebPFormat.Load(imageBuf);
            //            #endregion

            //            delegateDrawDesktop d = new delegateDrawDesktop(DrawDesktop);
 
            //            picBox.Invoke(d, image);

            //        }

            //    }; 
            #endregion

            #region 收到RTCP 侦事件
            //RecRtcpReportPacket += (sender, p) =>
            //    {
            //        if (IsControler)//如果是控制者
            //        {
            //            UdpRemoteDesketOrder DesketOrder = new UdpRemoteDesketOrder();
            //            DesketOrder.orderType = UdpRemoteDesketOrder.OrderType.NONE;
            //            sendRtcpControlPacket(DesketOrder);//发送一个假操作，维持RTP Session
            //            Console.WriteLine("发送假操作成功.");
            //        }
            //    };
            #endregion

            #region 连接成功事件
            TransmitConnected += (sender, connectedType) =>
            {
                if (IsControler)//如果是控制者
                {

                }
                else//如果是被控制者
                {
                    SendDesktop();//要求对方发送一张新的桌面图片
                }
            };
            #endregion
        }

        #endregion

        #region 绘制桌面图片代理
        delegate void delegateDrawDesktop(Image image);
        private void DrawDesktop(Image image)
        {
            picBox.Image = image;
            picBox.Refresh();
        }
        #endregion

        #region 发送一张本地桌面图片给对方
        /// <summary>
        /// 发送一张本地桌面图片给对方
        /// </summary>
        private void SendDesktop()
        {

            Rectangle screenArea = Rectangle.Empty;
            foreach (System.Windows.Forms.Screen screen in
                      System.Windows.Forms.Screen.AllScreens)
            {
                screenArea = Rectangle.Union(screenArea, screen.Bounds);
            }

            if (sc == null)
                sc = new OurSoftware.Video.ScreenCaptureStream(screenArea);
            sc.FrameInterval =2000;
            sc.NewFrame += (s, e) =>
                {
                    Image myScreen;
                    float screenPix = (float)screenArea.Width / (float)screenArea.Height;

                    if (screenPix >= 1.6)
                        myScreen = ((Image)e.Frame).GetThumbnailImage(1280, 720, null, IntPtr.Zero);
                    else
                        myScreen = ((Image)e.Frame).GetThumbnailImage(1024, 768, null, IntPtr.Zero);

                    //myScreen = ((Image)e.Frame).GetThumbnailImage(800, 600, null, IntPtr.Zero);

                    //MemoryStream ms = new MemoryStream();
                    //myScreen.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    //Image image = Image.FromStream(ms);
                    
                    #region MJPEG算法
                    //Image image = myScreen;
                    //Rtp.JpegFrame jpegFrame = new Rtp.JpegFrame(image, 20);//30
                    //sendJpegFrame(jpegFrame);
                    #endregion

                    if (!System.IO.File.Exists("WebP.dll"))
                        WebPFormat.DeCompress();

                    byte[] imageBuf =WebPFormat.Save(30, (Bitmap)myScreen); 
                    sendFrame(imageBuf);
                };
            sc.Start();
        }
     
        #endregion
 
        #region 关闭
        /// <summary>>
        /// 关闭 
        /// </summary>
        public void Close()
        {
            if (sc != null)
                sc.Stop();
            
            Dispose();
        }
        #endregion
    }
}
